
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import javax.swing.JFrame;


public class GameServer extends JFrame{

	private int RELAY_PORT = 7001;

	Socket[] relays;
	Socket[] androids;

	List<String> msgs = Collections.synchronizedList(new ArrayList<String>());

	public GameServer() {

		relays = new Socket[4];
		androids = new Socket[4];

		try {
			ServerSocket s = new ServerSocket(RELAY_PORT);

			// aquire relay connections
			for (int i = 0; i < 4; i++) {
				relays[i] = s.accept();
			}

			new Thread(new DataSender(relays));

			// aquire android connections
			for (int i = 0; i < 4; i++) {
				androids[i] = s.accept();
				new Thread(new DataReceiver(androids[i]));
			}

		} catch (Exception e) {
			System.out.println("Couldnt aquire connections");
			System.exit(0);
		}

		System.out.println("all connections good");
	}

	private void addMessage(String msg) {
		synchronized (msgs) {
			msgs.add(msg);
		}
	}

	public static void main(String[] args) {
		GameServer g = new GameServer();
	}

	private class DataReceiver implements Runnable {

		private DataInputStream incoming;

		public DataReceiver(Socket incoming) {
			try {
				this.incoming = new DataInputStream(incoming.getInputStream());
			}
			catch (Exception e) {

			}
		}

		public void run() {
			while (true) {
				String msg = "";

				// read message
				try {
					int msgType = incoming.readInt();
					int identifier = incoming.readInt();

					switch (msgType) {
					case 1:
						msg = msgType + ";" + identifier + ";" + incoming.readInt();
						break;
					case 2:
						msg = msgType + ";" + identifier + ";" + incoming.readUTF();
						break;
					default:
						break;
					}


				}
				catch(Exception e) {

				}

				// add message to queue
				if (!msg.equals("")) {
					synchronized (msgs) {
						msgs.add(msg);
					}
				}
			}
		}
	}

	private class DataSender implements Runnable {

		DataOutputStream[] relays;

		public DataSender(Socket[] relays) {
			try {
			DataOutputStream[] relayData = new DataOutputStream[relays.length];
			for (int i = 0; i < relays.length; i++) {
				relayData[i] = new DataOutputStream(relays[i].getOutputStream());
			}
			this.relays = relayData;
			}catch (Exception e) {

			}
		}

		public void run() {
			try {

				while(true) {
					// if messages exist, broadcast them
					if (!msgs.isEmpty()) {
						synchronized (msgs) {
							for (String s: msgs) {
								String[] strings = s.split(";");
								for(DataOutputStream d: relays) {
									switch (Integer.parseInt(strings[0])) {
									case 1:
										d.writeInt(Integer.parseInt(strings[0]));
										d.writeInt(Integer.parseInt(strings[1]));
										d.writeInt(Integer.parseInt(strings[2]));
										break;
									case 2:
										d.writeInt(Integer.parseInt(strings[0]));
										d.writeInt(Integer.parseInt(strings[1]));
										d.writeUTF(strings[2]);
										break;
									default:
											break;
									}
								}
							}
						}
					}else {
						Thread.sleep(100);
					}
				}

			}catch (Exception e) {

			}
		}
	}
}
